package com.shbatis.session;

import com.shbatis.core.ShMappedStatement;
import com.shbatis.core.SqlSessionFactory;

import java.io.Closeable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;

/**
 * @Auther: sh
 * @Version 1.0
 * @Description: 会话接口
 */
public class SqlSession implements Closeable {

    private final SqlSessionFactory sqlSessionFactory;


    public SqlSession(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    public void commit() {
        try {
            sqlSessionFactory.getTransaction().commit();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void rollback() {
        try {
            sqlSessionFactory.getTransaction().rollback();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void close() {
        try {
            sqlSessionFactory.getTransaction().close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public int insert(String statement, Object parameter) {
        Connection connection = sqlSessionFactory.getTransaction().getConnection();
        ShMappedStatement shMappedStatement = sqlSessionFactory.getMappedStatementMap().get(statement);
        String oldSql = shMappedStatement.getSql();
        String newSql = oldSql.replaceAll("#\\{[a-zA-Z0-9_\\$]*}", "?");
        System.out.println("执行sql: " + newSql);
        Map<Integer, String> map = new HashMap<>();
        int index = 1;
        while (oldSql.indexOf("#") >= 0) {
            int beginIndex = oldSql.indexOf("#") + 2;
            int endIndex = oldSql.indexOf("}");
            String val = oldSql.substring(beginIndex, endIndex).trim();  // 每一个参数
            map.put(index++, val);
            oldSql = oldSql.substring(endIndex + 1);
        }
//        map.forEach((k, v) -> {
//            System.out.print(String.format("参数%d: %s  ", k, v));
//        });
        PreparedStatement ps;
        try {
            ps = connection.prepareStatement(newSql);
            map.forEach((k, v) -> {
                try {
                    String getMethodName = "get" + v.toUpperCase().charAt(0) + v.substring(1);
                    Method getMethod = parameter.getClass().getDeclaredMethod(getMethodName);
                    System.out.print(String.format("执行参数%d: %s  ", k, getMethod.invoke(parameter)));
                    ps.setString(k, getMethod.invoke(parameter).toString());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
            System.out.println();
            int count = ps.executeUpdate();
//            connection.commit();
            ps.close();
            return count;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public Object selectOne(String statement, Object parameter) {
        Connection connection = sqlSessionFactory.getTransaction().getConnection();
        ShMappedStatement shMappedStatement = sqlSessionFactory.getMappedStatementMap().get(statement);
        String oldSql = shMappedStatement.getSql();
        String newSql = oldSql.replaceAll("#\\{[a-zA-Z0-9_\\$]*}", "?");
        PreparedStatement ps = null;
        ResultSet rs = null;
        Object obj = null;
        System.out.println("执行sql: " + newSql);
        try {
            ps = connection.prepareStatement(newSql);
            ps.setString(1, parameter.toString());
            rs = ps.executeQuery();
            if (rs.next()) {
                String resultType = shMappedStatement.getResultType();
                Class<?> aClass = Class.forName(resultType);
                Constructor<?> con = aClass.getDeclaredConstructor();
                obj = con.newInstance();

                ResultSetMetaData rsmd = rs.getMetaData();
                int columnCount = rsmd.getColumnCount();
                for (int i = 1; i <= columnCount; i++) {
                    String columnName = rsmd.getColumnName(i);
                    columnName = underscoreToCamel(columnName);
                    String setMethodName = "set" + columnName.substring(0, 1).toUpperCase() + columnName.substring(1);
                    Method setMethod = aClass.getDeclaredMethod(setMethodName, aClass.getDeclaredField(columnName).getType());
                    setMethod.invoke(obj, rs.getString(columnName));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("转换失败", e);
        }
        return obj;
    }

    public static   String underscoreToCamel(String underscoreName) {
        if (underscoreName == null || underscoreName.isEmpty()) {
            return underscoreName;
        }

        StringBuilder result = new StringBuilder();
        boolean nextUpperCase = false;

        for (int i = 0; i < underscoreName.length(); i++) {
            char c = underscoreName.charAt(i);
            if (c == '_') {
                nextUpperCase = true;
            } else {
                if (nextUpperCase) {
                    result.append(Character.toUpperCase(c));
                    nextUpperCase = false;
                } else {
                    result.append(Character.toLowerCase(c));
                }
            }
        }
        return result.toString();
    }

}

